import java.util.ArrayList;
import java.util.Iterator;


public class TablaFuncion {
		
		ArrayList<filaTFuncion> tablaFuncion;
		int posicionTS;
		ArrayList<String> pilaVariablesActuales;
	
		public TablaFuncion(int posicionTS){
	
			this.tablaFuncion = new ArrayList<filaTFuncion>();
			this.posicionTS = posicionTS; 
			this.pilaVariablesActuales = new ArrayList<String>();

		}
	
		

		public int obtenerPosicion(String lexema){
			int posicion=-1,i=0; boolean encontrado=false;
			System.out.println("\nTFuncion: ObtenerPosicion: "+lexema);

			if (!(tablaFuncion).isEmpty()){
				Iterator<filaTFuncion> iteradorFila = (tablaFuncion).iterator();
				String cadena;
				
					while (iteradorFila.hasNext() && !encontrado){
						cadena = (iteradorFila.next()).lexema;

						if (lexema.equals(cadena)){
							posicion = i;
							encontrado=true;
						}
						i++;
					}
							
			}else{
				posicion = -1;
			}
			
			System.out.println("\nTFuncion: ObtenerPosicion: "+lexema+ " = " + posicion);
			return posicion;
		}
		
				
		
		public boolean insertarParametro(String parametro, tipo tipo){
			boolean error = true;int posicion;int indice;
			System.out.println("\nTFuncion: InsertarParametro "+parametro);

			if (parametro.equals("ACTUAL")){
				
				
				if ((indice = pilaVariablesActuales.get(0).indexOf("|"))!=-1){
					
					posicion = obtenerPosicion ( pilaVariablesActuales.get(0).substring(0, indice) );
					if ( pilaVariablesActuales.get(0).length() > indice+1 )
						error = tablaFuncion.get(posicion).tablaVector.actualizarTVector( Character.getNumericValue(pilaVariablesActuales.get(0).charAt(indice+1) )  , tipo);
					else 
						System.out.println("TS: InsertarVariable: "+pilaVariablesActuales.get(0)+" no se ha podido actualizar");

				
				}else{
					posicion=obtenerPosicion(pilaVariablesActuales.get(0));
					if (posicion != -1){
						System.out.println("\nTFuncion: InsertarParametro: Si estaba en la tabla funcion");
						tablaFuncion.get(posicion).tipo = tipo;
						error = false;
					}else{
						System.out.println("\nTFuncion: InsertarParametro: No estaba en la tabla funcion: Crear fila: " + pilaVariablesActuales.get(0));
						filaTFuncion fila = new filaTFuncion(pilaVariablesActuales.get(0), tipo, 0, null);
						tablaFuncion.add(fila);
						error = false;
					}
				}
			}else{	
				
				
				if ((indice = parametro.indexOf("|"))!=-1){
					
					posicion = obtenerPosicion ( parametro.substring(0, indice) );
					if ( parametro.length() > indice+1 )
						error = tablaFuncion.get(posicion).tablaVector.actualizarTVector( Character.getNumericValue(parametro.charAt(indice+1) )  , tipo);
					else 
						System.out.println("TS: InsertarVariable: "+parametro+" no se ha podido actualizar");
				
					}else{
					
					posicion=obtenerPosicion(parametro);
	
					if (posicion != -1){
						System.out.println("\nTFuncion: InsertarParametro: Si estaba en la tabla funcion: Error");
						error = true;	
					}else{
						System.out.println("\nTFuncion: InsertarParametro: No estaba en la tabla funcion: Crear fila: " + parametro);
						filaTFuncion fila = new filaTFuncion(parametro, tipo, 0, null);
						tablaFuncion.add(fila);
						error = false;
					}	
				}
			}
			return error;	
		}
		
		
		
		
		
		public boolean cambiarContextoVariable(String lexema){
			if (lexema.equals("null"))
				pilaVariablesActuales.remove(0);
			else
				this.pilaVariablesActuales.add(0, lexema);
			
			System.out.println("TFuncion: CambiarContextoVariable: pila de variables actuales: "+ pilaVariablesActuales);

			return false;
		}
		

		
		
	public tipo obtenerTipo(String lexema){
		tipo tipo = null;
		int posicion=0;
		
		if (lexema.equals("ACTUAL")){
			lexema = pilaVariablesActuales.get(0);
		}
		
			posicion = obtenerPosicion(lexema);
			if (posicion==-1){
				
			}else{
				tipo = tablaFuncion.get(posicion).tipo;
			}
		
		return tipo;
	}
		
		

	public boolean actualizarTipo(String lexema, tipo tipo) {
		boolean error = true;
		
		int posicion = obtenerPosicion(lexema);
		
		if (posicion == -1){
			error = true;
		}else{
			tablaFuncion.get(posicion).tipo = tipo;
			error = false;
		}
		return error;
	}
	
	
	
	
	
	
	
	
	
	
		
		
		
	
	
	
		
		
		
		
		
		
		public boolean eliminarTFuncion(){
			boolean error = true;
			
			if (tablaFuncion != null){
					tablaFuncion.removeAll(tablaFuncion);
					error = false;
			}
			
			return error;
		}
		
		
		
		
		
		
		
		
		public boolean eliminarElementoTFuncion(String lexema){
			
			boolean encontrado = false, error = true;
			int i=0;
			if (tablaFuncion != null){

			Iterator<filaTFuncion> iteradorFila = tablaFuncion.iterator();
			filaTFuncion fila;
			
				while (iteradorFila.hasNext() && !encontrado){
					
					fila = iteradorFila.next();
					if (lexema.equals(fila.lexema))
						encontrado=true;
					else
						i++;
				}
				
			if (encontrado)
				System.out.println(lexema);
				tablaFuncion.remove(i);
				error=false;
			}
			return error;
			
		}



		public boolean insertarVector(String lexema, int dimension){ 
		boolean error=true; int posicion;
		filaTFuncion fila=null; 
		TablaVector tablaVector = null;
		
		System.out.println("TFuncion: InsertarVector: "+lexema + " dimension " + dimension);
				
			posicion = obtenerPosicion(lexema);
			
			if (posicion!=-1){
				
				tablaFuncion.get(posicion).tipo = tipo.VECTOR;
				tablaVector = new TablaVector();
				tablaFuncion.get(posicion).tablaVector = tablaVector;
				tablaFuncion.get(posicion).dimension = dimension;
				
				for (int i=0; i<dimension;i++){
					tablaFuncion.get(posicion).tablaVector.insertarTVector(i, tipo.VAR_DESCONOCIDA);
				}
				
				
				System.out.println("TFuncion: InsertarVector: Si estaba en tabla: Modifica a tipo vector "+lexema);
				error = false;
	
			}else{	
				tablaVector = new TablaVector();
				fila = new filaTFuncion(lexema, tipo.VECTOR, dimension, tablaVector);
				tablaFuncion.add(fila);
				System.out.println("TFuncion: InsertarVector: No estaba en tabla: Crear filaTS: "+lexema);
				error = false;
			}
		
		System.out.println("TFuncion: InsertarVector: error "+ error);

		return error;
	}



		public String obtenerVariableActual (int i){
			return pilaVariablesActuales.get(i);
		}



		public int obtenerDimension(String lexema){
			int dimension = 0;
			int posicion=0;
					
			System.out.println("TFuncion: ObtenerDimension: lexema "+ lexema);
			

			if (lexema.equals("ACTUAL")){
				lexema = pilaVariablesActuales.get(0);
			}
					
			posicion = obtenerPosicion(lexema);
					
			if (posicion!=-1 && (obtenerTipo(lexema) == tipo.VECTOR) ){
			
				dimension = tablaFuncion.get(posicion).dimension;
			}
				
			System.out.println("TFuncion: ObtenerDimension: lexema "+ lexema + " dimension " + dimension);
				
			return dimension;
		}



		public int obtenerDesplazamiento(String lexema) {
			int posicion = obtenerPosicion(lexema);
							
			return tablaFuncion.get(posicion).desplazamiento;
			
		}



		public int actualizarDesplazamiento(int contador) {
			int contadorFuncion = contador;
			System.out.println("TFuncion: actualizarDesplazamiento");

			for (filaTFuncion elemento : tablaFuncion){
				System.out.println(elemento.lexema + " " + elemento.tipo);

				switch (elemento.tipo){
				case ENTERO: 
					elemento.desplazamiento = contadorFuncion;
					contadorFuncion = contadorFuncion + 8;
					break;
				case BOOL: 
					elemento.desplazamiento = contadorFuncion;
					contadorFuncion = contadorFuncion + 8;
					break;
				case STRING: 
					elemento.desplazamiento = contadorFuncion;
					contadorFuncion = contadorFuncion + 8;
					break;
				case VECTOR: 
					elemento.desplazamiento = contadorFuncion;
					contadorFuncion = elemento.tablaVector.actualizarDesplazamiento(contadorFuncion);
					break;
				default: elemento.desplazamiento = contadorFuncion;
				contadorFuncion = contadorFuncion + 8;

				}					
			}
			
			return contador;

		}



		public int obtenerTotalDesplazamiento() {
			return tablaFuncion.get( tablaFuncion.size()-1 ).desplazamiento;
		}




		
		
}
